// Copyright (C) 2020, MinIO, Inc.
//
// This code is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License, version 3,
// as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License, version 3,
// along with this program.  If not, see <http://www.gnu.org/licenses/>

package configmaps

import (
	"fmt"
	"time"

	miniov2 "github.com/minio/operator/pkg/apis/minio.min.io/v2"
	"gopkg.in/yaml.v2"
)

type globalConfig struct {
	ScrapeInterval     time.Duration `yaml:"scrape_interval"`
	EvaluationInterval time.Duration `yaml:"evaluation_interval"`
}

// StaticConfig contains the static configuration for prometheus
type StaticConfig struct {
	Targets []string `yaml:"targets"`
}

// TLSConfig contains the tls configuration for prometheus
type TLSConfig struct {
	CAFile string `yaml:"ca_file"`
}

// ScrapeConfig contains the scrape configuration for prometheus
type ScrapeConfig struct {
	JobName       string         `yaml:"job_name"`
	BearerToken   string         `yaml:"bearer_token"`
	MetricsPath   string         `yaml:"metrics_path"`
	Scheme        string         `yaml:"scheme"`
	TLSConfig     TLSConfig      `yaml:"tls_config"`
	StaticConfigs []StaticConfig `yaml:"static_configs"`
}

// PrometheusConfig contains the prometheus configuration
type PrometheusConfig struct {
	Global        globalConfig   `yaml:"global"`
	ScrapeConfigs []ScrapeConfig `yaml:"scrape_configs"`
}

// ConfigFile returns the prometheus config yaml
func (p *PrometheusConfig) ConfigFile() string {
	d, err := yaml.Marshal(p)
	if err != nil {
		panic(fmt.Sprintf("error marshaling to yaml: %v", err))
	}

	configFileContent := fmt.Sprintf(`# This file and config-map is generated by MinIO Operator.
# DO NOT EDIT.

%s`, d)
	return configFileContent
}

// GetPrometheusConfig returns configuration for Prometheus.
func GetPrometheusConfig(t *miniov2.Tenant, accessKey, secretKey string) *PrometheusConfig {
	bearerToken := t.GenBearerToken(accessKey, secretKey)
	minioTargets := t.MinIOServerHostAddress()
	minioScheme := "http"
	if t.TLS() {
		minioScheme = "https"
	}

	// populate config
	promConfig := &PrometheusConfig{
		Global: globalConfig{
			ScrapeInterval:     miniov2.MinIOPrometheusScrapeInterval,
			EvaluationInterval: 30 * time.Second,
		},
		ScrapeConfigs: []ScrapeConfig{},
	}

	if len(t.Spec.PrometheusOperatorScrapeMetricsPaths) == 0 {
		t.Spec.PrometheusOperatorScrapeMetricsPaths = []string{"/minio/v2/metrics/cluster"}
	}

	for index, scrape := range t.Spec.PrometheusOperatorScrapeMetricsPaths {
		promConfig.ScrapeConfigs = append(promConfig.ScrapeConfigs, ScrapeConfig{
			JobName:     fmt.Sprintf("%s-%d", t.PrometheusOperatorAddlConfigJobName(), index),
			BearerToken: bearerToken,
			MetricsPath: scrape,
			Scheme:      minioScheme,
			TLSConfig: TLSConfig{
				CAFile: "/var/run/secrets/kubernetes.io/serviceaccount/ca.crt",
			},
			StaticConfigs: []StaticConfig{
				{
					Targets: []string{minioTargets},
				},
			},
		})
	}

	return promConfig
}
